package com.ug.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.ug.common.enums.ErrorCode;
import com.ug.common.exception.SystemException;
import com.ug.system.entity.monitor.RedisCacheInfo;
import com.ug.system.entity.monitor.ServerInfo;
import com.ug.system.service.MonitorApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Properties;

/**
 * @Author LY
 * @create 2024/8/2 14:48
 * @Description 应用信息监控服务
 * https://redis.io/docs/latest/commands/info/?ref=techvblogs.com
 */
@Service
@RequiredArgsConstructor
public class MonitorApplicationServiceImpl implements MonitorApplicationService {

    private final RedisTemplate<String, ?> redisTemplate;

    @Override
    public ServerInfo getServerInfo() {
        return ServerInfo.fillServerInfo();
    }

    @Override
    public RedisCacheInfo getRedisCacheInfo() {
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::info);
        Properties commandStats = (Properties) redisTemplate.execute(
                (RedisCallback<Object>) connection -> connection.info("commandstats")
        );
        Long dbSize = redisTemplate.execute(RedisServerCommands::dbSize);
        if (commandStats == null || info == null) {
            throw new SystemException(ErrorCode.REDIS_INFO_ERROR);
        }

        RedisCacheInfo cacheInfo = new RedisCacheInfo();
        cacheInfo.setInfo(info);
        cacheInfo.setDbSize(dbSize);
        cacheInfo.setCommandStats(new ArrayList<>());

        commandStats.stringPropertyNames().forEach(key -> {
            String property = commandStats.getProperty(key);
            RedisCacheInfo.CommandStatusDTO commonStatus = new RedisCacheInfo.CommandStatusDTO();
            commonStatus.setName(StrUtil.removePrefix(key, "cmdstat_"));
            commonStatus.setValue(StrUtil.subBetween(property, "calls=", ",usec"));

            cacheInfo.getCommandStats().add(commonStatus);
        });
        return cacheInfo;
    }
}
